package cn.phub.basic.service.impl;

import cn.phub.basic.constant.BaseConstant;
import cn.phub.basic.dto.RegisterDto;
import cn.phub.basic.exception.MyException;
import cn.phub.basic.service.IVerifyCodeService;
import cn.phub.basic.util.StrUtils;
import cn.phub.basic.util.VerifyCodeUtils;
import cn.phub.user.domain.User;
import cn.phub.user.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.concurrent.TimeUnit;

@Service
public class VerifyCodeServiceImpl implements IVerifyCodeService {
    //注入Redis
    @Autowired
    private RedisTemplate redisTemplate;

    @Autowired
    private UserMapper userMapper;

    @Override
    public String graph(String key) {
        //校验key是否为空
        if (!StringUtils.hasLength(key)){
            throw new MyException("空的,不行");
        }
        //直接生成新的值覆盖旧的code 不需要校验是否发过验证码
        String code = StrUtils.getComplexRandomString(4);
        //储存Redis 设置过期时间 使用前端给我的UUID为key code为值
        redisTemplate.opsForValue().set(key,code,5, TimeUnit.MINUTES);
        //调用工具类方法生成图片
        return VerifyCodeUtils.VerifyCode(105,40,code);
    }

    @Override
    public void smsCode(RegisterDto dto) {
        String type = dto.getType();

        if ("register".equals(type)) {
            //发送注册验证码
            sendRegisterCode(dto);
        }else{//发送绑定验证码
            sendBinderCode(dto);
        }

    }


    /**
     * 真正的发送验证码
     */
    private void sendSmsCode(String businessKey){
        //校验验证码是否已经发送过
        String smsCodeKey = businessKey;
        //根据手机号拼接业务键  从redis获取短信验证码 key  register:17606731246
        Object smsCodeTmp = redisTemplate.opsForValue().get(smsCodeKey);
        String smsCode = "";
        if (smsCodeTmp != null) {
            //获取到了  判断是否过了重发时间1分钟
            Long oldTime = Long.valueOf(smsCodeTmp.toString().split(":")[1]);
            if (System.currentTimeMillis()-oldTime <= 1*60*1000) {
                //小于一分钟，报错：请勿重复获取验证码
                throw new MyException("再点我要骂人了!");
            }
            //大于一分钟，使用原来的验证码，刷新过期时间
            smsCode = smsCodeTmp.toString().split(":")[0];
        }else {
            //获取不到 说明已经过期  直接生成新的验证码
            smsCode = StrUtils.getComplexRandomString(4);
        }
        //保存reids 设置过期时间3分钟
        String smsCodeValue = smsCode + ":" + System.currentTimeMillis();
        redisTemplate.opsForValue().set(
                smsCodeKey,
                smsCodeValue,
                4,
                TimeUnit.MINUTES
        );
        //发送短信验证码
//        SmsUtils.sendMsg(phone,"您的验证码是：" + smsCode + "请在三分钟内使用!");
        System.out.println("您的验证码是：" + smsCode + "请在三分钟内使用!");
    }

    /**
     * 发送绑定验证码
     * @param dto
     */
    private void sendBinderCode(RegisterDto dto) {
        String businessKey = BaseConstant.SmsConstant.BUSINESS_BINDER_PREFIX+dto.getPhone();
        sendSmsCode(businessKey);
    }

    /**
     * 发送注册验证码
     */
    private void sendRegisterCode(RegisterDto dto) {
        String phone = dto.getPhone();
        String imageCodeKey = dto.getImageCodeKey();
        String imageCodeValue = dto.getImageCodeValue();
        String type = dto.getType();

        //校验参数,空校验
        if (StringUtils.isEmpty(phone)
                || StringUtils.isEmpty(imageCodeKey)
                || StringUtils.isEmpty(imageCodeValue)) {
            throw new MyException("参数不能为空!");
        }

        //校验手机号是否已经被注册
        User user = userMapper.loadByPhone(phone);
        if (user != null) {
            throw new MyException("手机号已经注册,请直接登录!");
        }
        //图形验证码校验 根据imageCodeKey 从redis获取图形验证码
        Object imageValueTmp = redisTemplate.opsForValue().get(imageCodeKey);
        //没有拿到 图形验证码失效 报错
        if (imageValueTmp == null) {
            throw new MyException("图形验证码已过期,请重新获取!");
        }
        //拿到了  判断输入的图形验证码是否正确(不区分大小写)
        if (!imageValueTmp.toString().equalsIgnoreCase(imageCodeValue)) {
            throw new MyException("请输入正确的图形验证码!");
        }
        String businessKey = BaseConstant.SmsConstant.BUSINESS_REGISTER_PREFIX+phone;
        sendSmsCode(businessKey);
    }
}
